package com.neouton.common.util;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy;
import com.alibaba.excel.write.style.row.SimpleRowHeightStyleStrategy;
import com.neouton.crm.entity.DynamicExcelData;
import com.neouton.encrypt.typehandler.Encrypt;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.jetbrains.annotations.NotNull;

import javax.servlet.http.HttpServletResponse;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.*;

public class EasyExcelUtils {

    public static @NotNull List<Map<String, Object>> getDataList(List list, List<String> timeFormatArr) throws IntrospectionException, IllegalAccessException, InvocationTargetException {
        List<Map<String, Object>> dataList = new ArrayList<>();
        SimpleDateFormat shortTime = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for (Object item : list) {
            Class cl = item.getClass();
            Field[] declaredFields = cl.getDeclaredFields();
            Map<String, Object> map = new HashMap<>();
            for(Field field: declaredFields) {
                String fieldName = field.getName();
                if (!"serialVersionUID".equals(fieldName)) {
                    PropertyDescriptor pd = new PropertyDescriptor(fieldName, cl);
                    Method getMethod = pd.getReadMethod();
                    Object invoke = getMethod.invoke(item);
                    if (!Objects.isNull(invoke)) {
                        if (field.getType().getName().equals("java.sql.Timestamp") ||field.getType().getName().equals("java.util.Date")) {
                            if (timeFormatArr.contains(fieldName)) {
                                invoke = timeFormat.format(invoke);
                            } else {
                                invoke = shortTime.format(invoke);
                            }
                        } else if ("com.neouton.encrypt.typehandler.Encrypt".equals(field.getType().getName())) {
                            invoke = ((Encrypt) invoke).getValue();
                        }
                    } else if (Objects.isNull(invoke)) {
                        invoke = "";
                    }

                    map.put(fieldName, invoke);
                }
            }

            dataList.add(map);
        }
        return dataList;
    }

    /**
     *
     * @param response
     * @param nameMap 表头名称及对应字段
     * @param list 数据集
     * @param sheetName sheet名称
     * @param menu 合并单元格索引
     * @param mergeByPrimaryKey  是否按按主键合并
     * @param primaryKey 合并主键名称
     * @throws IOException
     */
    public static void dynamicExport(HttpServletResponse response,
                                     LinkedHashMap<String, DynamicExcelData> nameMap,
                                     List<Map<String, Object>> list, String sheetName,
                                     Integer[] menu,
                                     boolean mergeByPrimaryKey,
                                     Object primaryKey) throws IOException {
        if (nameMap == null) {
            throw new RuntimeException("请填写好映射表数据");
        }

        int size = list.size();
        List<List<String>> dataList = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            dataList.add(new ArrayList<>());
        }

        //获取表头
        ArrayList<List<String>> head = new ArrayList<>();
        for (Map.Entry<String, DynamicExcelData> titleMap : nameMap.entrySet()) {
            DynamicExcelData data = titleMap.getValue();
            head.add(Collections.singletonList(data.getName()));
        }

        //数据重组
        for (int i = 0; i < list.size(); i++) {
            Map<String, Object> map = list.get(i);
            List<String> columns = dataList.get(i);
            for (Map.Entry<String, DynamicExcelData> sortNameEntry : nameMap.entrySet()) {
                String key = sortNameEntry.getKey();
                Object value = map.get(key);
                columns.add(value != null ? String.valueOf(value) : sortNameEntry.getValue().getDefaultValue());
            }
        }

        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");

        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        //设置背景颜色
        headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
        //设置头居中
        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        contentWriteCellStyle.setWrapped(true); // 自动换行
        // 字体策略
        WriteFont contentWriteFont = new WriteFont();
        contentWriteFont.setFontHeightInPoints((short) 10);  // 字体大小
        contentWriteCellStyle.setWriteFont(contentWriteFont);

        HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);

        if (mergeByPrimaryKey) {
            EasyExcel.write(response.getOutputStream()).head(head)
                    .sheet(sheetName)
                    .registerWriteHandler(new ExcelFillCellMergeStrategyUtils(0, menu, mergeByPrimaryKey, primaryKey, list))
                    .registerWriteHandler(new SimpleColumnWidthStyleStrategy(25)) // 简单的列宽策略，列宽20
                    .registerWriteHandler(new SimpleRowHeightStyleStrategy((short) 35, (short) 25)) // 简单的行高策略：头行高，内容行高
                    .registerWriteHandler(horizontalCellStyleStrategy)
                    .doWrite(dataList);
        } else {
            EasyExcel.write(response.getOutputStream()).head(head)
                    .sheet(sheetName)
                    .registerWriteHandler(new SimpleColumnWidthStyleStrategy(25)) // 简单的列宽策略，列宽20
                    .registerWriteHandler(new SimpleRowHeightStyleStrategy((short) 35, (short) 25)) // 简单的行高策略：头行高，内容行高
                    .registerWriteHandler(horizontalCellStyleStrategy)
                    .doWrite(dataList);
        }
    }
}
